package com.example.dqreptile.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.example.dqreptile.entity.Charact;
import com.example.dqreptile.entity.Monster;
import com.example.dqreptile.entity.Skill;
import com.example.dqreptile.service.ICharactService;
import com.example.dqreptile.service.IMonsterService;
import com.example.dqreptile.service.ISkillService;
import com.example.dqreptile.service.SaveHttpDataService;
import com.example.dqreptile.utils.HttpClientUtils;
import com.example.dqreptile.utils.MyChromeDriver;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.Connection;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.seimicrawler.xpath.JXDocument;
import org.seimicrawler.xpath.JXNode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;

import java.io.*;
import java.net.MalformedURLException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;

@Service
@Slf4j
public class SaveHttpDataServiceImpl implements SaveHttpDataService {

    @Autowired
    IMonsterService iMonsterService;

    @Autowired
    ISkillService iSkillService;

    @Autowired
    ICharactService iCharactService;

    @Autowired
    HttpClientUtils httpClientUtils;

    @Autowired
    MyChromeDriver myChromeDriver;

   final String SEPARATOR = File.separator;

    private static String GOOGLEWEB = "https://translate.google.cn/#view=home&op=translate&sl=ja&tl=en&text=";

    /**
     * 按照等级  遍历怪物连接
     *
     * @param
     * @return
     */
    @Override
    public List<String> listMosterUrl() {

        List<String> list = new ArrayList<>();
        Document bodyStr = null;
        JXDocument jxDocument = null;
        List<JXNode> jxNodes = null;
        try {
            bodyStr = Jsoup.connect("http://dqmsl-search.net/picturebook/rank").get();
            jxDocument = JXDocument.create(bodyStr);
            jxNodes = jxDocument.selN("//img[@class='rotateImageButton']");
        } catch (Exception e) {
            log.error("的连接失败,已停止！" + e.getLocalizedMessage());
            return list;
        }
        int count = 0;
        for (JXNode jxnode : jxNodes) {
            JXNode jxNodeA = jxnode.selOne("..");
            String url = "http://dqmsl-search.net" + jxNodeA.asElement().attr("href");

            //String src = jxnode.asElement().attr("src");
            try {
                //String name = jxNodeA.asElement().nextElementSibling().text();
                //log.info("第{}只怪物主页是：{} 图片连接：{} 怪物名字为：{} ", count, url, src, name);

                if (Integer.parseInt(url.split("=")[1]) > 0) {
                }
                list.add(url);
                count++;
            } catch (Exception e) {
                continue;
            }
        }

        return list;

    }

    /**
     * 保存怪物详细资料
     *
     * @param url
     * @return
     * @throws InterruptedException
     */
    @Override
    @Async("taskExecutor")
    public Future<String> saveMosterByUrl(String url) throws InterruptedException {
        Monster monster = new Monster();
        Document bodyStr = null;
        JXDocument jxDocument = null;
        //主要DIV
        JXNode mainNode = null;
        try {
            bodyStr = Jsoup.connect(url).get();
            jxDocument = JXDocument.create(bodyStr);
            // /html/body/div[2]/div/div[1]/div[1]
            mainNode = jxDocument.selNOne("//div[@class='mbox']");

        } catch (Exception e) {
            log.error("的连接失败,已停止！" + e.getLocalizedMessage());
            return new AsyncResult<String>("error url is  " + url);
        }

        //获取所有模块 标题节点
        List<JXNode> titleNodes = mainNode.sel("//span[@class='detmhead']");
        //根据标题 取主要DIV节点
        Map<String, JXNode> moduleDivs = new HashMap<>();
        for (int i = 0; i < titleNodes.size(); i++) {
            String moduleName = titleNodes.get(i).asElement().text();
            JXNode moduleDiv = titleNodes.get(i).selOne("..");
            moduleDivs.put(moduleName, moduleDiv);
        }
        //log.info("moduleDivs的大小为：{} 其中 节点->ステータス:{}",titleNodes.size(),moduleDivs.get("とくぎ").asElement().html());

        //  怪物说明
        String mStory = getNodeText(mainNode.selOne("/div[3]/span"));
        monster.setmStory(mStory);

        String mNameZh = getNodeText(mainNode.selOne("/div[2]/h1"));
        monster.setmNameJp(mNameZh);

        //  基础项目  /div[3]/div[3]/div/span
        JXNode basePojoDiv = moduleDivs.get("基本項目");
        if (basePojoDiv != null) {
            List<JXNode> basePojo = basePojoDiv.sel("/div/span");

            String mCode = basePojo.get(0).asElement().text();
            monster.setmCode(mCode);

            String level = basePojo.get(1).selOne("/a[1]").asElement().attr("href").split("=")[1];
            monster.setmLevel(level);
            //种系
            String germline = basePojo.get(2).asElement().text().split("：")[1];
            monster.setmGermline(germline);

            String type = basePojo.get(3).asElement().text().split("：")[1];
            monster.setmType(type);
            // 重量   暂时没有
            String weight = basePojo.get(4).asElement().text().split("：")[1];
            monster.setWeight(weight);

            String maxLevel = basePojo.get(5).asElement().text().split("：")[1];
            monster.setmLevel(maxLevel);
            //log.info("{}:{}:{}:{}:{}:{}", mCode, level, germline, type, weight, maxLevel);
        }

        //------ 基本属性 ----------
        //              /div[5]/div[2]/div/div[1]/span
        JXNode baseAttr = moduleDivs.get("ステータス");
        if (baseAttr != null) {
            String mHp = getNodeText(baseAttr.selOne("//*[@id=\"hpid\"]"));
            monster.setmHpMax(Integer.parseInt(mHp));
            String mMp = getNodeText(baseAttr.selOne("//*[@id=\"mpid\"]"));
            monster.setmMpMax(Integer.parseInt(mMp));
            String mAttack = getNodeText(baseAttr.selOne("//*[@id=\"ofid\"]"));
            monster.setmAttackMax(Integer.parseInt(mAttack));
            String mDf = getNodeText(baseAttr.selOne("//*[@id=\"dfid\"]"));
            monster.setmDefenseMax(Integer.parseInt(mDf));
            //速度
            String mDx = getNodeText(baseAttr.selOne("//*[@id=\"dxid\"]"));
            monster.setmAgileMax(Integer.parseInt(mDx));
            //智慧
            String mEi = getNodeText(baseAttr.selOne("//*[@id=\"eiid\"]"));
            monster.setmIntelligenceMax(Integer.parseInt(mEi));
            String mTotal = getNodeText(baseAttr.selOne("//*[@id=\"ssmid\"]"));
            monster.setmTotalAttr(Integer.parseInt(mTotal.replaceAll(",", "")));

            //log.info("基本属性 HP{}:MP{}:ACK{}:DF{}:DX{}:EI{}:TITAL{}", mHp, mMp, mAttack, mDf, mDx, mEi, mTotal);
            String remark = getNodeHtml(baseAttr.selOne("//*[@id=\"powerupInheritInfoImage\"]"));
            monster.setmAttrRemark(remark);
            // log.info("备注HTML为：{}", remark);
        }

        //技能
        JXNode skillDiv = moduleDivs.get("とくぎ");
        if (skillDiv != null) {
            List<JXNode> skillNodes = skillDiv.sel("/div/span/a");
            List<Skill> skillList = new ArrayList<>();
            if (skillNodes != null) {
                for (JXNode jxNode : skillNodes) {
                    String skillId = null;
                    try {
                        skillId = jxNode.asElement().attr("href").split("=")[1];
                        Skill skill = iSkillService.findOne(Integer.valueOf(skillId));
                        if (skill == null) {
                            skill = new Skill();
                            skill.setsId(Integer.parseInt(skillId));
                            iSkillService.saveSkill(skill);
                        }
                        skillList.add(skill);

                    } catch (NumberFormatException e) {
                        log.error("添加技能ID={}失败！", skillId);
                    }
                }
                monster.setSkillList(skillList);
                log.info("技能数量：{}", skillList.size());

            }

        }

        //特性
        JXNode characteristicDiv = moduleDivs.get("特性");
        if (characteristicDiv != null) {
            List<JXNode> characteristicNodes = characteristicDiv.sel("/div/span/a");
            List<Charact> charactList = new ArrayList<>();
            for (JXNode jxNode : characteristicNodes) {
                String charactId = null;
                try {
                    if (jxNode != null) {
                        charactId = jxNode.asElement().attr("href").split("=")[1];
                        Charact charact = iCharactService.findOne(Integer.parseInt(charactId));
                        if (charact == null) {
                            charact = new Charact();
                            charact.setcId(Integer.parseInt(charactId));
                            iCharactService.saveCharact(charact);
                        }
                        charactList.add(charact);
                    }
                } catch (NumberFormatException e) {
                    log.error("添加特性ID={}失败！", charactId);
                }

            }
            monster.setCharactList(charactList);
            log.info("特性数量：{}", charactList.size());

        }

        // 队长 特性  直接保存了！
        JXNode captainCharactDiv = moduleDivs.get("リーダー特性");
        if (captainCharactDiv != null) {
            List<JXNode> jxNodes = captainCharactDiv.sel("/div/span/a");
            if (jxNodes != null) {
                String ccMsg = "";
                for (JXNode jxNode : jxNodes) {
                    ccMsg += getNodeText(jxNode);
                }
                monster.setmCaptainCharact(ccMsg);
            }

        }

        iMonsterService.save(monster);
        return new AsyncResult<String>("success url is  " + url);
    }


    /**
     * 多线程 使用 翻译工具
     * @param msgMps
     * @return
     * @throws UnsupportedEncodingException
     */
    @Override
    @Async("taskExecutor")
    public Future<Map<String,String>> GoogleTranslateService(Map<String,String> msgMps) throws UnsupportedEncodingException, MalformedURLException, InterruptedException {
        WebDriver webDriver = myChromeDriver.getOnlineDriver();
      //  Document bodyStr = null;
        WebElement element = null;
        try {
            webDriver.get("https://translate.google.cn/#view=home&op=translate&sl=ja&tl=zh-CN&text="+URLEncoder.encode(msgMps.get("value"),"UTF-8"));
            // /html/body/div[2]/div/div[1]/div[1]
            element =  webDriver.findElement(By.xpath("/html/body/div[2]/div[2]/div[1]/div[3]/div[1]/div[1]/div[2]/div[3]/div[1]/div[2]/div/span[1]/span"));
            System.out.println(element.getText());
        } catch (Exception e) {
            log.error("{}的数据转换失败,已停止！错误：{}" ,msgMps,e.getLocalizedMessage());
            return new AsyncResult<>(msgMps);
        }
   /*     webDriver.close();
        webDriver.quit();*/
        Thread.sleep(1000);
        return new AsyncResult<>(msgMps);
    }


    /**
     * 获取技能URL LIST
     *
     * @return
     */
    @Override
    public List<String> listSkillUrl() {

        String skillBaseUrl = "http://dqmsl-search.net/picturebook/skill?tokugiId=";

        List<String> list = new ArrayList<>();

        Document bodyStr = null;
        JXDocument jxDocument = null;
        List<JXNode> jxNodes = null;
        try {
            bodyStr = Jsoup.connect("http://dqmsl-search.net/monster/search").get();
            jxDocument = JXDocument.create(bodyStr);

            jxNodes = jxDocument.selN("//*[@id=\"getMonsterSearchForm\"]/div[3]/div/span[@class=\"enclose2\"]");
        } catch (Exception e) {
            log.error("的连接失败,已停止！" + e.getLocalizedMessage());
            return list;
        }

        if (jxNodes != null) {

            for (JXNode jxNode : jxNodes) {
                List<JXNode> jxNodeAs = jxNode.sel("/span[2]/span");

                for (JXNode jxNode1 : jxNodeAs) {
                    list.add(skillBaseUrl + jxNode1.asElement().attr("id"));
                }

            }
        }

        return list;
    }


    @Override
    @Async("taskExecutor")
    public Future<String> saveSkillInfo(String url) {

        Skill skill=new Skill();

        Document bodyStr = null;
        JXDocument jxDocument = null;
        JXNode mainNode = null;
        //System.out.println(GOOGLEWEB + URLEncoder.encode(jsonObject.get("value").toString(),"UTF-8"));
        try {
            bodyStr = Jsoup.connect(url).get();
            jxDocument = JXDocument.create(bodyStr);
            // /html/body/div[2]/div/div[1]/div[1]
            mainNode = jxDocument.selNOne("//div[@class=\"mboxb\"][1]");
        } catch (Exception e) {
            log.error("的连接失败,已停止！" + e.getLocalizedMessage());
            return new AsyncResult<>("run " + url + "  error!");
        }

        String sSkillId=url.split("=")[1];
        skill.setsId(Integer.parseInt(sSkillId));

        String skillType =  mainNode.selOne("/div/span/span/span").asElement().attr("class").split(" ")[1];
        skill.setsType(skillType);

        String skillName = mainNode.selOne("/div/span/span").asElement().text().split("&")[0];
        skill.setsName(skillName);

        //技能效果
        List<JXNode> jxNodes=mainNode.sel("/div/div/div[1]/p[@Style=\"margin-bottom:5px;\"]");
        if(jxNodes!=null){
            String skillEffectUrl = "";
            for (JXNode jxNode:jxNodes) {
                skillEffectUrl+=getNodeText(jxNode);
            }
            skill.setsEffect(skillEffectUrl);
        }

        JXNode jxNode = mainNode.selOne("/div/div/img");

        String imgUrl = "http://dqmsl-search.net"+jxNode.asElement().attr("src");
        String localImgPath="";
        try {
             localImgPath = savaImage(imgUrl,"F:\\workspace\\dqreptile\\src\\main\\resources\\skillImg",imgUrl.substring(imgUrl.lastIndexOf("/")+1,imgUrl.length()));
            skill.setsImgPath(localImgPath);
        } catch (IOException e) {

            log.error("异常：{} 保存图片失败！网络路径：{}",e.getLocalizedMessage(),imgUrl);
        }
        iSkillService.saveSkill(skill);
        return new AsyncResult<String>("run " + url + "  success!");
    }

    /**
     * 获取节点 TEXT 判空
     *
     * @param jxNode
     * @return
     */
    public String getNodeText(JXNode jxNode) {

        if (jxNode == null) {
            return "";
        }
        return jxNode.asElement().text();
    }


    /**
     * 获取节点 TEXT 判空
     *
     * @param jxNode
     * @return
     */
    public String getNodeHtml(JXNode jxNode) {

        if (jxNode == null) {
            return "";
        }
        return jxNode.asElement().html();
    }


    /**
     * 保存图片
     * @param url
     * @param filePath
     * @param fileName
     */
    private String savaImage(String url, String filePath, String fileName) throws IOException {
        String localPath="";

        Connection.Response imgBytes = Jsoup.connect(url).ignoreContentType(true).execute();
        byte[] img = imgBytes.bodyAsBytes();

        BufferedOutputStream bos = null;
        FileOutputStream fos = null;
        File file = null;
        File dir = new File(filePath);
        try {
            //判断文件目录是否存在
            if (!dir.exists() && dir.isDirectory()) {
                dir.mkdirs();
            }
            file = new File(filePath + SEPARATOR + fileName);
            fos = new FileOutputStream(file);
            bos = new BufferedOutputStream(fos);
            bos.write(img);
            localPath  = filePath + SEPARATOR + fileName;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return localPath;
    }

}
